package com.qianheng.kit.base.java.thread;

import com.qianheng.kit.base.java.thread.pool.MyThreadPool;
import com.qianheng.kit.base.java.thread.threads.Example;
import lombok.extern.slf4j.Slf4j;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;

@Slf4j
public class FutureDemo {
    public void test() throws ExecutionException, InterruptedException {
        CompletableFuture<String> washing = CompletableFuture.supplyAsync(Example.自动洗锅300到500ms);
        CompletableFuture<String> cai = CompletableFuture.supplyAsync(Example.切菜配菜300到400ms);
        CompletableFuture.allOf(washing, cai).get();//如果仅写allof，不写.get()，就不会等待
        CompletableFuture<String> caocai = CompletableFuture.supplyAsync(Example.炒菜500到600ms);
        caocai.get();
    }

    /**
     * 测试CompletableFuture的异常传递方式。
     * 仅使用allOf，子线程会执行，但主线程不会等待。子线程的异常会被存到future，如果主线程不去操作它，它就不会被感知。
     */
    public void test异常处理() {
        long start = System.currentTimeMillis();
        log.info("开始 test异常处理");
        List<CompletableFuture<String>> futures = new ArrayList<>();
        futures.add(CompletableFuture.supplyAsync(Example.异常));
        futures.add(CompletableFuture.supplyAsync(Example.异常));

        //
        CompletableFuture<Void> allOf = CompletableFuture.allOf(futures.toArray(new CompletableFuture[] {}));
        log.info("执行allOf结束 时间={}", System.currentTimeMillis() - start);//执行allOf结束 时间=10

        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
        log.info("主线程sleep1000后， 时间={}", System.currentTimeMillis() - start);

        try {
            allOf.join();
            log.info("执行join结束 时间={}", System.currentTimeMillis() - start);//不能到这一步
        } catch (Exception ex) {
            log.error("执行join()方法,抓到异常,时间={}", System.currentTimeMillis() - start, ex);//执行join()方法,抓到异常,时间=618
        }

        futures.get(0).exceptionally(ex -> {
            log.error("执行exceptionally回调,获取异常,时间={}", System.currentTimeMillis() - start, ex);//执行exceptionally回调,获取异常,时间=622
            return null;
        });

        try {
            futures.get(0).get();
        } catch (Exception ex) {
            log.error("执行get(),抓到异常,时间={}", System.currentTimeMillis() - start, ex);//执行get(),抓到异常,时间=622
        }
    }
}
